/*
 * Created on Jul 2, 2004
 *
 * To change the template for this generated file go to
 * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
 */
package abdn.graph.growl;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;

import abdn.graph.growl.editor.EditorGUI;
import abdn.graph.ontobrowser.KRPolicy;
import abdn.graph.ontobrowser.OBNode;

/**
 * @author skrivov, rwilliams
 *
 * To change the template for this generated type comment go to
 * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
 */
public class MetadataPanel extends JPanel implements TableModelListener, ActionListener
{
  static final int COL_PREFIX = 0;
  static final int COL_URI = 1;
  static final int COL_IMP = 2;

  static final String CMD_NEW = "new";
  static final String CMD_DELETE = "delete";

  KRPolicyOWL krPolicy;
  OWLMetadata metadata;
  EditorGUI editor;

	private CsTableModel model = null;

  private javax.swing.JTextField nsTextField = null;
  private javax.swing.JLabel nsLabel = null;
	private javax.swing.JLabel csLabel = null;
	private javax.swing.JScrollPane jScrollPane = null;
	private javax.swing.JTable csTable = null;
	private javax.swing.JTextArea commentTextArea = null;
	private javax.swing.JLabel commentLabel = null;
	private javax.swing.JButton newButton = null;
	private javax.swing.JButton deleteButton = null;

	/**
	 * This is the default constructor
	 */
	public MetadataPanel(KRPolicy p, EditorGUI e)
  {
    super();
    editor = e;
    metadata = (krPolicy = (KRPolicyOWL)p).getMetadata();
		initialize();
	}

	/**
	 *
	 */
	private void initialize() {
		this.setLayout(null);
    this.add(getNsTextField(), null);
    this.add(getNsLabel(), null);
		this.add(getCsLabel(), null);
		this.add(getJScrollPane(), null);
		this.add(getCommentTextArea(), null);
		this.add(getCommentLabel(), null);
		this.add(getNewButton(), null);
		this.add(getDeleteButton1(), null);
		this.setSize(677, 388);
		this.setPreferredSize(new java.awt.Dimension(500, 500));
    initializeControls();
	}

  private void initializeControls()
  {
    if( metadata != null )
    {
      // initialize base uri
      nsTextField.setText(metadata.getBaseURI().toString());
      // initialise concept space table
      CsTableModel model = (CsTableModel)csTable.getModel();
      model.clear();
      List namespaces = metadata.getNamespaces();
      for(Iterator i = namespaces.iterator(); i.hasNext();)
      {
        OWLMetadata.NameSpace ns = (OWLMetadata.NameSpace)i.next();
        model.addRow(ns.getPrefix(), ns.getUri(), ns.isImported());
      }
      // make last column (with checkbox) narrower
      int j, max = model.getColumnCount();
      for( j = 0; j < model.getColumnCount(); j++)
      {
        TableColumn column = csTable.getColumnModel().getColumn(j);
        column.setPreferredWidth((j == max - 1) ? 30 : 100);
      }
    }
  }

  /**
   * This method initializes nsLabel
   *
   * @return javax.swing.JLabel
   */
  private javax.swing.JLabel getNsLabel() {
    if (nsLabel == null) {
      nsLabel = new javax.swing.JLabel();
      nsLabel.setBounds(30, 24, 125, 16);
      nsLabel.setText("Default Namespace");
    }
    return nsLabel;
  }

  /**
   * This method initializes nsTextField
   *
   * @return javax.swing.JTextArea
   */
  private javax.swing.JTextField getNsTextField() {
    if (nsTextField == null) {
      nsTextField = new javax.swing.JTextField();
      nsTextField.setBounds(30, 44, 621, 20);
      nsTextField.setAutoscrolls(false);
    }
    return nsTextField;
  }

  /**
	 * This method initializes csLabel
	 *
	 * @return javax.swing.JLabel
	 */
	private javax.swing.JLabel getCsLabel() {
		if (csLabel == null) {
			csLabel = new javax.swing.JLabel();
			csLabel.setBounds(30, 88, 125, 16);
			csLabel.setText("Concept Space Table");
		}
		return csLabel;
	}
	/**
	 * This method initializes csTable
	 *
	 * @return javax.swing.JTable
	 */
	private javax.swing.JTable getCsTable() {
		if (csTable == null) {
			model = new CsTableModel();
			csTable = new JTable(model);
      csTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
      model.addTableModelListener(this);
    }
		return csTable;
	}

	/**
	 * This method initializes jScrollPane
	 *
	 * @return javax.swing.JScrollPane
	 */
	private javax.swing.JScrollPane getJScrollPane() {
		if (jScrollPane == null) {
			jScrollPane = new javax.swing.JScrollPane();
			jScrollPane.setBounds(27, 114, 619, 100);
			jScrollPane.setViewportView(getCsTable());
		}
		return jScrollPane;
	}
	/**
	 * This method initializes commentTextArea
	 *
	 * @return javax.swing.JTextArea
	 */
	private javax.swing.JTextArea getCommentTextArea() {
		if (commentTextArea == null) {
			commentTextArea = new javax.swing.JTextArea();
			commentTextArea.setBounds(30, 264, 621, 112);
			commentTextArea.setRows(0);
			commentTextArea.setWrapStyleWord(true);
			commentTextArea.setLineWrap(true);
			commentTextArea.setAutoscrolls(false);
		}
		return commentTextArea;
	}

	/**
	 * This method initializes commentLabel
	 *
	 * @return javax.swing.JLabel
	 */
	private javax.swing.JLabel getCommentLabel() {
		if (commentLabel == null) {
			commentLabel = new javax.swing.JLabel();
			commentLabel.setBounds(30, 136, 134, 19);
			commentLabel.setText("Comment");
		}
		return commentLabel;
	}

  /**
	 * This method initializes newButton
	 *
	 * @return javax.swing.JButton
	 */
	private javax.swing.JButton getNewButton() {
		if (newButton == null) {
			newButton = new javax.swing.JButton();
			newButton.setBounds(434, 86, 105, 22);
			newButton.setText("Add New Row");
      newButton.setActionCommand(CMD_NEW);
      newButton.addActionListener(this);
		}
		return newButton;
	}

  /**
	 * This method initializes deleteButton1
	 *
	 * @return javax.swing.JButton
	 */
	private javax.swing.JButton getDeleteButton1() {
		if (deleteButton == null) {
			deleteButton = new javax.swing.JButton();
			deleteButton.setBounds(555, 86, 87, 20);
			deleteButton.setText("Delete");
      deleteButton.setActionCommand(CMD_DELETE);
      deleteButton.addActionListener(this);
		}
		return deleteButton;
	}

  /**
   * Method getMetadata - get the current values from the various controls
   *  and set values in the KRPolicyOWL object
   *
   */
  public void getMetadata()
  {
    String ns = nsTextField.getText();
    try
    {
      metadata.setBaseURI(new URI(ns));
    }
    catch (URISyntaxException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  public void setMetadata(KRPolicy p)
  {
    metadata = ((KRPolicyOWL)p).getMetadata();
    initializeControls();
    repaint();
  }

  class CsTableModel extends AbstractTableModel {
    private String[] columnNames = {"Prefix",
                                    "URI",
                                    "Imported"};

    private ArrayList data = new ArrayList();

    public void clear()
    {
      data = new ArrayList();
    }

    public void addRow(String prefix, String uri, boolean imported)
    {
      Object row[] = {prefix, uri, new Boolean(imported)};
      data.add(row);
    }

    public void removeRow(int row)
    {
      data.remove(row);
    }

    public int getColumnCount() {
      return columnNames.length;
    }

    public int getRowCount() {
      return data.size();
    }

    public String getColumnName(int col) {
      return columnNames[col];
    }

    public Object getValueAt(int row, int col) {
      return ((Object[])data.get(row))[col];
    }

      /*
       * JTable uses this method to determine the default renderer/
       * editor for each cell.  If we didn't implement this method,
       * then the last column would contain text ("true"/"false"),
       * rather than a check box.
       */
      public Class getColumnClass(int c) {
          return getValueAt(0, c).getClass();
      }

      /*
       * Don't need to implement this method unless your table's
       * editable.
       */
      public boolean isCellEditable(int row, int col)
      {
        return true;
      }

      /*
       * Don't need to implement this method unless your table's
       * data can change.
       */
      public void setValueAt(Object value, int row, int col) {
        ((Object[])data.get(row))[col] = value;
        fireTableCellUpdated(row, col);
      }
  }

  /* (non-Javadoc)
   * @see javax.swing.event.TableModelListener#tableChanged(javax.swing.event.TableModelEvent)
   */
  public void tableChanged(TableModelEvent e)
  {
    int row = e.getFirstRow();
    int column = e.getColumn();
    CsTableModel model = (CsTableModel)e.getSource();
    if( column >= 0 && row >= 0 )
    {
      String columnName = model.getColumnName(column);
      Object data = model.getValueAt(row, column);
      switch(column)
      {
        case COL_PREFIX:
        case COL_URI:
          String uriStr = (String)model.getValueAt(row, COL_URI);
          String prefix = (String)model.getValueAt(row, COL_PREFIX);
          if( uriStr.length() > 0 )
          {
            try
            {
              URI uri = new URI(uriStr);  // does syntax check of uri string
              if( prefix.length() > 0 )
              {
                if( metadata.getNamespaces().size() == row )  // adding by entering data in a previously blank row
                {
                  metadata.addNamespace(uriStr, prefix, ((Boolean)model.getValueAt(row, COL_PREFIX)).booleanValue() );
                  updateOnAdd(prefix, uriStr);
                }
                else
                {
                  String oldPrefix = metadata.getPrefixOfURI(uriStr);
                  String oldURI = metadata.getURIOfPrefix(prefix);
                  metadata.changeNamespace(row, uriStr, prefix);
                  updateOnChange(oldPrefix, oldURI, prefix, uriStr);
                }
              }
            }
            catch (URISyntaxException e1)
            {
              JOptionPane.showMessageDialog(this, "URI error: " + uriStr);
            }
          }
          break;
        case COL_IMP:
          if( row < metadata.getNamespaces().size() )  // make sure this is not a blank row
          {
            if( JOptionPane.showConfirmDialog(this, "Changing imports requires ontology to be saved and reloaded. Proceed?", "Save and reload", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION )
            {
              OWLMetadata.NameSpace ns = (OWLMetadata.NameSpace)metadata.getNamespaces().get(row);
              ns.setImported(((Boolean)data).booleanValue());
              //editor.fileSaveAndReload();
// TODO save and reload
            }
          }
          break;
      }
    }
  }

  /* (non-Javadoc)
   * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
   */
  public void actionPerformed(ActionEvent e)
  {
    String cmd = e.getActionCommand();
    // TODO Auto-generated method stub
    if( cmd.equals(CMD_NEW))
    {
      processActionNew();
    }
    else if( cmd.equals(CMD_DELETE) )
    {
      processActionDelete();
    }
  }

  private void processActionNew()
  {
    CsTableModel model = (CsTableModel)csTable.getModel();
    if( model.getRowCount() == metadata.getNamespaces().size()) // make sure blank row doesn't already exist
    {
      model.addRow("", "", false);
      model.fireTableDataChanged();
    }
    int row = model.getRowCount() - 1;
    csTable.clearSelection();
    csTable.addRowSelectionInterval(row, row);
  }

  private void processActionDelete()
  {
    int row = csTable.getSelectedRow();
    if( row >= 0 )
    {
      String uriStr = (String)model.getValueAt(row, COL_URI);
      String prefix = (String)model.getValueAt(row, COL_PREFIX);
      updateOnDelete(prefix, uriStr);
      CsTableModel model = (CsTableModel)csTable.getModel();
      metadata.deleteNamespace(row);
      model.removeRow(row);
      model.fireTableDataChanged();
    }
  }

  private void updateOnAdd(String prefix, String uri)
  {
    Vector nodes = krPolicy.esdOntoBrowser.getTGPanel().getCompleteEltSet().getNodes();
    for(Iterator i = nodes.iterator(); i.hasNext();)
    {
      OBNode node = (OBNode)i.next();
      String ns = node.getNamespace();
      if( uri.equals(ns) )
      {
        node.setNamespace(prefix);
      }
    }
  }

  private void updateOnChange(String oldPrefix, String oldURI, String prefix, String uri)
  {
    Vector nodes = krPolicy.esdOntoBrowser.getTGPanel().getCompleteEltSet().getNodes();
    for(Iterator i = nodes.iterator(); i.hasNext();)
    {
      OBNode node = (OBNode)i.next();
      String ns = node.getNamespace();
      if( oldPrefix != null ) // change prefix of URI
      {
        if( oldPrefix.equals(ns) )
          node.setNamespace(prefix);
      }
      if( oldURI != null ) // change URI of prefix
      {
        if( prefix.equals(ns) )
        {
          node.setNamespace(oldURI);  // remove existing prefix
        }
        else if( ns.equals(uri) )     // set prefix if node matches new prefix uri
        {
          node.setNamespace(prefix);
        }
      }
    }
    krPolicy.esdOntoBrowser.getTGPanel().repaint();
  }

  private void updateOnDelete(String prefix, String uri)
  {
    Vector nodes = krPolicy.esdOntoBrowser.getTGPanel().getCompleteEltSet().getNodes();
    for(Iterator i = nodes.iterator(); i.hasNext();)
    {
      OBNode node = (OBNode)i.next();
      String ns = node.getNamespace();
      if( prefix.equals(ns) )
      {
        node.setNamespace(uri);
      }
    }
  }



} //  @jve:visual-info  decl-index=0 visual-constraint="10,10"
